D:\git\skunkworks\herald-for-cpp\herald\include\herald\sensor_delegate.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2020-2021 Herald Project Contributors |
2 | | // SPDX-License-Identifier: Apache-2.0 |
3 | | // |
4 | | |
5 | | #ifndef HERALD_SENSOR_DELEGATE_H |
6 | | #define HERALD_SENSOR_DELEGATE_H |
7 | | |
8 | | #include "datatype/sensor_type.h" |
9 | | #include "datatype/proximity.h" |
10 | | #include "datatype/payload_data.h" |
11 | | #include "datatype/target_identifier.h" |
12 | | #include "datatype/immediate_send_data.h" |
13 | | #include "datatype/location.h" |
14 | | #include "datatype/sensor_state.h" |
15 | | |
16 | | #include <variant> |
17 | | #include <array> |
18 | | |
19 | | namespace herald { |
20 | | |
21 | | using namespace datatype; |
22 | | |
23 | | // /// \brief Base interface for classes wishing to implement callbacks for core low-level Herald proximity and presence events. |
24 | | // class SensorDelegate { |
25 | | // public: |
26 | | // SensorDelegate() = default; |
27 | | // virtual ~SensorDelegate() = default; |
28 | | |
29 | | |
30 | | // /// Detection of a target with an ephemeral identifier, e.g. BLE central detecting a BLE peripheral. |
31 | | // virtual void sensor(SensorType sensor, const TargetIdentifier& didDetect) = 0; |
32 | | |
33 | | // /// Read payload data from target, e.g. encrypted device identifier from BLE peripheral after successful connection. |
34 | | // virtual void sensor(SensorType sensor, const PayloadData& didRead, const TargetIdentifier& fromTarget) = 0; |
35 | | |
36 | | // /// Receive written immediate send data from target, e.g. important timing signal. |
37 | | // virtual void sensor(SensorType sensor, const ImmediateSendData& didReceive, const TargetIdentifier& fromTarget) = 0; |
38 | | |
39 | | // /// Read payload data of other targets recently acquired by a target, e.g. Android peripheral sharing payload data acquired from nearby iOS peripherals. |
40 | | // virtual void sensor(SensorType sensor, const std::vector<PayloadData>& didShare, const TargetIdentifier& fromTarget) = 0; |
41 | | |
42 | | // /// Measure proximity to target, e.g. a sample of RSSI values from BLE peripheral. |
43 | | // virtual void sensor(SensorType sensor, const Proximity& didMeasure, const TargetIdentifier& fromTarget) = 0; |
44 | | |
45 | | // /// Detection of time spent at location, e.g. at specific restaurant between 02/06/2020 19:00 and 02/06/2020 21:00 |
46 | | // template <typename LocationT> |
47 | | // void sensor(SensorType sensor, const Location<LocationT>& didVisit) {} |
48 | | |
49 | | // /// Measure proximity to target with payload data. Combines didMeasure and didRead into a single convenient delegate method |
50 | | // virtual void sensor(SensorType sensor, const Proximity& didMeasure, const TargetIdentifier& fromTarget, const PayloadData& withPayload) = 0; |
51 | | |
52 | | // /// Sensor state update |
53 | | // virtual void sensor(SensorType sensor, const SensorState& didUpdateState) = 0; |
54 | | // }; |
55 | | |
56 | | // TODO move this into a general header |
57 | | template<typename F, typename... Args, typename = decltype(std::declval<F>()(std::declval<Args&&>()...))> |
58 | | std::true_type isValidImpl(void*); |
59 | | |
60 | | template<typename F, typename... Args> |
61 | | std::false_type isValidImpl(...); |
62 | | |
63 | 0 | inline constexpr auto isValid = [] (auto f) { |
64 | 0 | return [](auto&&... args) { |
65 | 0 | return decltype(isValidImpl<decltype(f),decltype(args)&&...>(nullptr)){}; |
66 | 0 | }; |
67 | 0 | }; Unexecuted instantiation: memoryarena-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: datatypes-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: base64string-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: datetime-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: randomuuid-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: uint8-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: uint16-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: uint32-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: uint64-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: sha256-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: distribution-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: sensorlogger-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: errorcontactlog-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: data-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: datatypesdataderived-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: blemacaddress-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: targetidentifier-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: test-util.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: crossplatform-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: beaconpayload-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: extendeddata-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: fixedpayload-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: bledevice-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: sample-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: ranges-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: analysisrunner-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: analysissensor-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: gaussian-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: advertparser-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: bledatabase-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: blecoordinator-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z Unexecuted instantiation: coordinator-tests.cpp:??$?RV<lambda_0>@herald@@@<lambda_1>@herald@@QEBA?A?<auto>@@V<lambda_0>@1@@Z |
68 | | |
69 | | template<typename T> |
70 | | struct TypeT { |
71 | | using Type = T; |
72 | | }; |
73 | | |
74 | | template<typename T> |
75 | | constexpr auto type = TypeT<T>{}; |
76 | | |
77 | | template<typename T> |
78 | | T valueT(TypeT<T>); |
79 | | |
80 | | |
81 | | constexpr auto hasSensorFunction = isValid( |
82 | | [](auto&& s,auto&& sensor,auto&& didRead,auto&& fromTarget) -> |
83 | | decltype(((decltype(s))s).get().sensor(sensor,didRead,fromTarget)) {} |
84 | | ); |
85 | | // template<typename T,typename SE, typename DR, typename FT> |
86 | | // using HasSensorFunctionT = decltype(hasSensorFunction(std::declval<T>(),std::declval<SE>(),std::declval<DR>(),std::declval<FT>())); |
87 | | template<typename T,typename... Args> |
88 | | using HasSensorFunctionT = decltype(hasSensorFunction(std::declval<T>(),std::declval<Args>()...)); |
89 | | template<typename T,typename... Args> |
90 | | constexpr auto HasSensorFunctionV = HasSensorFunctionT<T,Args...>::value; |
91 | | |
92 | | /// \brief A set of variant typed Sensor Delegate instances. Delegate callbacks can be invoked on the whole set, if supported by each. |
93 | | template <typename... SensorDelegateTs> |
94 | | class SensorDelegateSet { |
95 | | public: |
96 | | static constexpr std::size_t Size = sizeof...(SensorDelegateTs); |
97 | | |
98 | | SensorDelegateSet(SensorDelegateTs&... dels) : |
99 | | //delegates({std::variant<std::reference_wrapper<SensorDelegateTs&...>>(std::reference_wrapper<SensorDelegateTs&...>(dels...))}) { |
100 | | // delegates(std::experimental::make_array({std::reference_wrapper<SensorDelegateTs&...>(dels...)})) { |
101 | | delegates(std::array< |
102 | | std::variant<std::reference_wrapper<SensorDelegateTs>...> |
103 | | ,Size |
104 | | >({std::variant<std::reference_wrapper<SensorDelegateTs>...>(dels)...})) { |
105 | | // addDelegates(0,dels...); |
106 | | } |
107 | | |
108 | | // auto begin() -> decltype(std::declval<std::array< |
109 | | // std::variant<std::reference_wrapper<SensorDelegateTs>...> |
110 | | // ,Size |
111 | | // >>().begin()) { |
112 | | // return delegates.begin(); |
113 | | // } |
114 | | |
115 | | // auto end() -> decltype(std::declval<std::array< |
116 | | // std::variant<std::reference_wrapper<SensorDelegateTs>...> |
117 | | // ,Size |
118 | | // >>().end()) { |
119 | | // return delegates.end(); |
120 | | // } |
121 | | |
122 | | /// \brief Detection of a target with an ephemeral identifier, e.g. BLE central detecting a BLE peripheral. |
123 | | void sensor(SensorType sensor, const TargetIdentifier& didDetect) { |
124 | | for (auto& delegateV : delegates) { |
125 | | std::visit([sensor,didDetect](auto&& arg) { |
126 | | // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS |
127 | | if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didDetect)>) { |
128 | | ((decltype(arg))arg).get().sensor(sensor,didDetect); // cast to call derived class function |
129 | | } |
130 | | }, delegateV); |
131 | | } |
132 | | } |
133 | | |
134 | | /// \brief Read payload data from target, e.g. encrypted device identifier from BLE peripheral after successful connection. |
135 | | void sensor(SensorType sensor, const PayloadData& didRead, const TargetIdentifier& fromTarget) { |
136 | | for (auto& delegateV : delegates) { |
137 | | std::visit([sensor,didRead,fromTarget](auto&& arg) { |
138 | | // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS |
139 | | if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didRead),decltype(fromTarget)>) { |
140 | | ((decltype(arg))arg).get().sensor(sensor,didRead,fromTarget); // cast to call derived class function |
141 | | } |
142 | | }, delegateV); |
143 | | } |
144 | | } |
145 | | |
146 | | /// \brief Receive written immediate send data from target, e.g. important timing signal. |
147 | | void sensor(SensorType sensor, const ImmediateSendData& didReceive, const TargetIdentifier& fromTarget) { |
148 | | for (auto& delegateV : delegates) { |
149 | | std::visit([sensor,didReceive,fromTarget](auto&& arg) { |
150 | | // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS |
151 | | if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didReceive),decltype(fromTarget)>) { |
152 | | ((decltype(arg))arg).get().sensor(sensor,didReceive,fromTarget); // cast to call derived class function |
153 | | } |
154 | | }, delegateV); |
155 | | } |
156 | | } |
157 | | |
158 | | /// \brief Read payload data of other targets recently acquired by a target, e.g. Android peripheral sharing payload data acquired from nearby iOS peripherals. |
159 | | void sensor(SensorType sensor, const DataSections<8>& didShare, const TargetIdentifier& fromTarget) { |
160 | | for (auto& delegateV : delegates) { |
161 | | std::visit([sensor,didShare,fromTarget](auto&& arg) { |
162 | | // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS |
163 | | if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didShare),decltype(fromTarget)>) { |
164 | | ((decltype(arg))arg).get().sensor(sensor,didShare,fromTarget); // cast to call derived class function |
165 | | } |
166 | | }, delegateV); |
167 | | } |
168 | | } |
169 | | |
170 | | /// \brief Measure proximity to target, e.g. a sample of RSSI values from BLE peripheral. |
171 | | void sensor(SensorType sensor, const Proximity& didMeasure, const TargetIdentifier& fromTarget) { |
172 | | for (auto& delegateV : delegates) { |
173 | | std::visit([sensor,didMeasure,fromTarget](auto&& arg) { |
174 | | // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS |
175 | | if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didMeasure),decltype(fromTarget)>) { |
176 | | ((decltype(arg))arg).get().sensor(sensor,didMeasure,fromTarget); // cast to call derived class function |
177 | | } |
178 | | }, delegateV); |
179 | | } |
180 | | } |
181 | | |
182 | | /// \brief Detection of time spent at location, e.g. at specific restaurant between 02/06/2020 19:00 and 02/06/2020 21:00 |
183 | | template <typename LocationT> |
184 | | void sensor(SensorType sensor, const Location<LocationT>& didVisit) { |
185 | | for (auto& delegateV : delegates) { |
186 | | std::visit([sensor,didVisit](auto&& arg) { |
187 | | // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS |
188 | | if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didVisit)>) { |
189 | | ((decltype(arg))arg).get().sensor(sensor,didVisit); // cast to call derived class function |
190 | | } |
191 | | }, delegateV); |
192 | | } |
193 | | } |
194 | | |
195 | | /// \brief Measure proximity to target with payload data. Combines didMeasure and didRead into a single convenient delegate method |
196 | | void sensor(SensorType sensor, const Proximity& didMeasure, const TargetIdentifier& fromTarget, const PayloadData& withPayload) { |
197 | | for (auto& delegateV : delegates) { |
198 | | std::visit([sensor,didMeasure,fromTarget,withPayload](auto&& arg) { |
199 | | // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS |
200 | | if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didMeasure),decltype(fromTarget),decltype(withPayload)>) { |
201 | | ((decltype(arg))arg).get().sensor(sensor,didMeasure,fromTarget,withPayload); // cast to call derived class function |
202 | | } |
203 | | }, delegateV); |
204 | | } |
205 | | } |
206 | | |
207 | | /// \brief Sensor state update |
208 | | void sensor(SensorType sensor, const SensorState& didUpdateState) { |
209 | | for (auto& delegateV : delegates) { |
210 | | std::visit([sensor,didUpdateState](auto&& arg) { |
211 | | // ONLY INVOKE IF WE KNOW THIS FUNCTION EXISTS |
212 | | if constexpr (HasSensorFunctionV<decltype(arg),decltype(sensor),decltype(didUpdateState)>) { |
213 | | ((decltype(arg))arg).get().sensor(sensor,didUpdateState); // cast to call derived class function |
214 | | } |
215 | | }, delegateV); |
216 | | } |
217 | | } |
218 | | |
219 | | private: |
220 | | std::array< |
221 | | std::variant<std::reference_wrapper<SensorDelegateTs>...> |
222 | | , |
223 | | Size |
224 | | > delegates; |
225 | | |
226 | | // template <typename LastT> |
227 | | // constexpr void addDelegates(int nextPos,LastT& last) { |
228 | | // delegates[nextPos] = std::reference_wrapper<LastT>(last); |
229 | | // } |
230 | | |
231 | | // template <typename FirstT, typename SecondT, typename... RestT> |
232 | | // constexpr void addDelegates(int nextPos,FirstT& first, SecondT& second, RestT&... rest) { |
233 | | // delegates[nextPos] = std::reference_wrapper<FirstT>(first); |
234 | | // ++nextPos; |
235 | | // addDelegates(nextPos,second,rest...); |
236 | | // } |
237 | | }; |
238 | | |
239 | | |
240 | | } // end namespace |
241 | | |
242 | | #endif |